package com.guisu.material.recyclerview

import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View

/**
- 支持上拉加载 下拉刷新的RecyclerView
- on 2022/11/7
 */
class LoadRefreshRecyclerView : RefreshRecyclerView {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    //上拉加载更多的辅助类
    private var loadViewCreator: LoadViewCreator? = null

    //上拉加载更多头部的高度
    private var loadViewHeight = 0

    //上拉加载更多的头部View
    private var loadView: View? = null

    //手指按下的位置
    private var fingerDownY = 0

    //当前是否正在拖动
    private var currentDrag = false

    //当前状态
    private var currentLoadStatus = 0

    companion object{
        //默认状态
        var LOAD_STATUS_NORMAL = 10

        //上拉加载更多状态
        var LOAD_STATUS_PULL_DOWN_REFRESH = 11

        //松开加载更多状态
        var LOAD_STATUS_LOOSEN_LOADING = 12

        //正在加载更多状态
        var LOAD_STATUS_LOADING = 13
    }

    //设置上拉加载更多
    fun addLoadViewCreator(loadViewCreator: LoadViewCreator) {
        this.loadViewCreator = loadViewCreator
        addLoadView()
    }

    override fun setAdapter(adapter: Adapter<*>?) {
        super.setAdapter(adapter)
        addLoadView()
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                //记录手指按下的位置,之所以写在dispatchTouchEvent里是因为如果我们处理了item点击事件，那么就不会进入onTouchEvent里面，所有应该在这里处理
                fingerDownY = ev.rawY.toInt()
            }
            MotionEvent.ACTION_UP -> {
                if (currentDrag) {
                    restoreLoadView()
                }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    /**
     * 重置上拉加载更多View
     */
    private fun restoreLoadView() {
        var currentBottomMargin = (loadView?.layoutParams as MarginLayoutParams).bottomMargin
        var finalBottomMargin = 0
        if (currentLoadStatus == LOAD_STATUS_LOOSEN_LOADING) {
            currentLoadStatus = LOAD_STATUS_LOADING
            loadViewCreator?.onLoading()
            listener?.onLoad()
        }

        val distance = currentBottomMargin - finalBottomMargin
        //回弹到指定位置
        val animator =
            ObjectAnimator.ofFloat(currentBottomMargin.toFloat(), finalBottomMargin.toFloat())
                .setDuration(distance.toLong())
        animator.addUpdateListener {
            val currentTopMargin = it.animatedValue
            setLoadViewMarginBottom(currentTopMargin as Float)
        }
        animator.start()
        currentDrag = false
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        if (loadViewCreator != null && loadView != null) {
            loadViewHeight = loadView!!.measuredHeight
        }
    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_MOVE -> {
                //当在最底部的时候才处理，否则不需要处理
                if (canScrollDown() || currentLoadStatus == LOAD_STATUS_LOADING) {
                    return super.onTouchEvent(ev)
                }
                //解决上拉加载更多自动滚动问题
                if (currentDrag) {
                    scrollToPosition(adapter!!.itemCount - 1)
                }

                //获取手指触摸拖拽的距离
                val distanceY = (ev.rawY - fingerDownY) * dragIndex
                //如果是已经到达底部，并且不断的向下拉，那么不断的改变marginBottom的值
                if (distanceY < 0) {
                    setLoadViewMarginBottom(-distanceY)
                    updateLoadStatus(-distanceY)
                    currentDrag = true
                    return true
                }
            }
        }
        return super.onTouchEvent(ev)
    }


    /**
     * 设置加载View的marginBottom
     */
    private fun setLoadViewMarginBottom(marginBottom: Float) {
        var finalMarginBottom = marginBottom.toInt()
        val marginLayoutParams = loadView!!.layoutParams as MarginLayoutParams
        if (finalMarginBottom < 0) {
            finalMarginBottom = 0
        }
        marginLayoutParams.bottomMargin = finalMarginBottom
        loadView?.layoutParams = marginLayoutParams
    }


    private fun canScrollDown(): Boolean {
        return canScrollVertically(1)
    }


    /**
     * 停止加载更多
     */
    fun onStopLoad() {
        currentLoadStatus = LOAD_STATUS_NORMAL
        restoreLoadView()
        loadViewCreator?.onStopLoad()
    }

    private fun updateLoadStatus(distanceY: Float) {
        currentLoadStatus = if (distanceY <= 0) {
            LOAD_STATUS_NORMAL
        } else if (distanceY < loadViewHeight) {
            LOAD_STATUS_PULL_DOWN_REFRESH
        } else {
            LOAD_STATUS_LOOSEN_LOADING
        }
        loadViewCreator?.onPull(distanceY.toInt(), loadViewHeight, currentLoadStatus)
    }

    private fun addLoadView() {
        if (adapter != null && loadViewCreator != null) {
            //添加底部加载更多View
            val view = loadViewCreator?.getLoadView(context, this)
            if (view != null) {
                addFooterView(view)
                this.loadView = view
            }
        }
    }

    private var listener: OnLoadMoreListener? = null
    fun setOnLoadMoreListener(listener: OnLoadMoreListener) {
        this.listener = listener
    }

    interface OnLoadMoreListener {
        fun onLoad()
    }
}

